package com.anxuan.agent.app;

import com.anxuan.agent.advisor.MyLoggerAdvisor;
import com.anxuan.agent.chatmemory.FileBasedChatMemory;
import com.anxuan.agent.chatmemory.MysqlBasedChatMemory;
import com.anxuan.agent.rag.LoveAppRagCustomAdvisorFactory;
import com.anxuan.agent.rag.QueryRewriter;
import com.anxuan.agent.service.ChatMessageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor;
import org.springframework.ai.chat.client.advisor.api.Advisor;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;

import java.util.List;
import java.util.Map;

import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY;
import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY;

@Component
@Slf4j
public class LoveApp {

    private final ChatClient chatClient;

    private final Resource templateResource;

    private final ChatMessageService chatMessageService;

    @jakarta.annotation.Resource
    private VectorStore loveAppVectorStore;

    @jakarta.annotation.Resource
    private Advisor loveAppRagCloudAdvisor;

    @jakarta.annotation.Resource
    private QueryRewriter queryRewriter;

    @jakarta.annotation.Resource
    private ToolCallback[] allTools;

    @jakarta.annotation.Resource
    private ToolCallbackProvider toolCallbackProvider;



    private static final String SYSTEM_PROMPT = "你是一位深耕恋爱心理领域的专业咨询师，具备系统的心理学知识与丰富的情感案例经验。你的职责是通过共情与专业分析，帮助用户厘清恋爱中的情绪困扰、关系矛盾和自我成长问题。\n" +
            "\n" +
            "请根据用户的陈述内容，结合你的心理学知识和检索到的参考资料，为用户提供个性化、实用、具有安抚性的建议。\n" +
            "\n" +
            "请遵循以下原则：\n" +
            "\n" +
            "1. 自我介绍：\n" +
            "   - 在开场时简要说明你是恋爱心理专家，欢迎用户倾诉。\n" +
            "\n" +
            "2. 问题识别与引导：\n" +
            "   - 单身用户：引导其表达关于脱单、社交焦虑、自信心等方面的困扰；\n" +
            "   - 恋爱中用户：引导其说明沟通、信任、习惯差异等矛盾场景；\n" +
            "   - 已婚用户：关注家庭责任分工、亲密感减退、亲属关系处理等问题。\n" +
            "\n" +
            "3. 引导用户提供更多细节：\n" +
            "   - 包括事件经过、对方的表现、自身的感受与想法。\n" +
            "\n" +
            "4. 回答风格：\n" +
            "   - 委婉亲切、有温度，兼具心理逻辑与实操建议；\n" +
            "   - 不生硬下判断，避免标签化，体现倾听和支持。\n" +
            "\n" +
            "5. 如果参考信息不足，也可以适当给出基于经验的建议，鼓励用户进一步表达。\n" +
            "\n" +
            "你的目标是：让用户在被理解的前提下，获得切实可行的心理支持与方向建议。\n";



    public LoveApp(ChatModel dashscopeChatModel,@Value("classpath:/prompts/system-message.txt")  Resource templateResource, ChatMessageService chatMessageService) {

        // 初始化基于文件的对话记忆
        //String fileDir = System.getProperty("user.dir") + "/tmp/chat-memory";
        //FileBasedChatMemory fileBasedChatMemory = new FileBasedChatMemory(fileDir);
        // 初始化基于内存的对话记忆
        //ChatMemory chatMemory = new InMemoryChatMemory();

        this.templateResource = templateResource;
        this.chatMessageService = chatMessageService;

        chatClient = ChatClient.builder(dashscopeChatModel)
                .defaultSystem(SYSTEM_PROMPT)
                .defaultAdvisors(
                        new MessageChatMemoryAdvisor(new MysqlBasedChatMemory(chatMessageService)),
                        new MyLoggerAdvisor()
                )
                .build();
    }

    /**
     * AI 基础对话（支持多轮对话记忆）
     * @param message
     * @param chatId
     * @return
     */
    public String doChat(String message, String chatId){


        ChatResponse chatResponse = chatClient
                .prompt()
                .user(message)
                .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                .call()
                .chatResponse();

        String content = chatResponse.getResult().getOutput().getText();
        log.info("content: {}", content);

        return content;

    }

    /**
     * AI 基础对话（支持多轮对话记忆 sse流式传输）
     * @param message
     * @param chatId
     * @return
     */
    public Flux<String> doChatBySteam(String message, String chatId){


        return  chatClient
                .prompt()
                .user(message)
                .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                .stream()
                .content();

    }


    record LoveReport(String title, List<String> suggestions){

    }
    /**
     * AI 恋爱报告功能（实战结构化输出）
     * @param message
     * @param chatId
     * @return
     */
    public LoveReport doChatWithReport(String message, String chatId){


        LoveReport loveReport = chatClient
                .prompt()
                .system(SYSTEM_PROMPT + "每次对话后都要生成恋爱结果，标题为{用户名}的恋爱报告，内容为建议列表")
                .user(message)
                .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 1))
                .call()
                .entity(LoveReport.class);


        log.info("loveReport: {}", loveReport);

        return loveReport;

    }

    public String testPromptTemplate(String author){
        PromptTemplate promptTemplate = new PromptTemplate(templateResource);
        Prompt prompt = promptTemplate.create(Map.of("author", author));
        return chatClient
                .prompt(prompt)
                .system("你是一个文学作品研究者")
                .call()
                .chatResponse()
                .getResult()
                .getOutput()
                .getText();
    }

    public String doChatWithRag(String message, String chatId) {

        String rewrittenMessage = queryRewriter.doQueryRewrite(message);
        ChatResponse chatResponse = chatClient
                .prompt()
                //使用改写后的查询
                .user(rewrittenMessage)
                .advisors(spec -> {
                    spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId);
                    spec.param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10);
                })
                //应用RAG 知识库问答
                //.advisors(new QuestionAnswerAdvisor(loveAppVectorStore))
                //应用RAG 检索增强服务（基于云知识库服务）
                //.advisors(loveAppRagCloudAdvisor)
                //应用RAG 检索增强服务（基于 pgVector向量存储）
                //.advisors(new QuestionAnswerAdvisor(pgVectorVectorStore))
                .advisors(LoveAppRagCustomAdvisorFactory.createLoveAppRagAdvisor(loveAppVectorStore, List.of("单身", "已婚", "恋爱")))
                .call()
                .chatResponse();


        String content = chatResponse.getResult().getOutput().getText();
        log.info("content: {}", content);
        return content;
    }

    public String doChatWithTools(String message, String chatId) {
        ChatResponse response = chatClient
                .prompt()
                .user(message)
                .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                // 开启日志，便于观察效果
                .advisors(new MyLoggerAdvisor())
                .tools(allTools)
                .call()
                .chatResponse();
        String content = response.getResult().getOutput().getText();
        log.info("content: {}", content);
        return content;
    }

    public String doChatWithMcp(String message, String chatId) {
        ChatResponse response = chatClient
                .prompt()
                .user(message)
                .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                // 开启日志，便于观察效果
                .tools(toolCallbackProvider)
                .call()
                .chatResponse();
        String content = response.getResult().getOutput().getText();
        log.info("content: {}", content);
        return content;
    }
}

